﻿using System;
using System.Windows.Input;


namespace DailyFx.UI
{

    public class RelayCommand<TTarget, TResult> : System.Windows.Input.ICommand, IResult
    {
		/// <summary>
		///		the command's execution method .
		/// </summary>
        private readonly Action<TResult> _executeMethod;

		/// <summary>
		///		check if can the command executes method .
		/// </summary>
        private readonly Func<TTarget, bool> _canExecuteMethod;

		/// <summary>
		/// 
		/// </summary>
        public RelayCommand ( Action<TResult> executeMethod,  Func<TTarget, bool> canExecuteMethod )
        {
            this._executeMethod = executeMethod;
            this._canExecuteMethod = canExecuteMethod;
            
			this.Completed = new WeakActionEvent<object> ();
        }

        public RelayCommand ( Action<TResult> executeMethod )
        {
            this._executeMethod = executeMethod;
            this._canExecuteMethod = x => { return true; };
            
			this.Completed = new WeakActionEvent<object> ();
        }
      
		/// <summary>
		///		
		/// </summary>
        public void Execute ( TResult parameter )
        {
            if ( this._executeMethod != null )
            {
                this._executeMethod ( parameter );
            }

            // now raises command's completed .
            if ( this.Completed != null)
            {
                this.Completed.Invoke(parameter);
            }
        }

	
		/// <summary>
		/// 
		/// </summary>
		public void Execute ( object parameter )
        {
            Execute ( (TResult)parameter );
        }

		/// <summary>
		///		Checks if this command can executes .
		/// </summary>
		public bool CanExecute ( TTarget parameter )
        {
            return this._canExecuteMethod == null || this._canExecuteMethod ( parameter );
        }

		/// <summary>
		///		
		/// </summary>
        public bool CanExecute ( object parameter )
        {
            return CanExecute( (TTarget)parameter );
        }

        

        /// <summary>
        ///		Occurs when changes occur that affect whether the command should executes.
        /// </summary>
        public event EventHandler CanExecuteChanged
        {
            add
            {
                if ( this._canExecuteMethod != null )
                {
                    CommandManager.RequerySuggested += value;
                }
            }

            remove
            {
                if ( this._canExecuteMethod != null )
                {
                    CommandManager.RequerySuggested -= value;
                }
            }
        }

		/// <summary>
		///		
		/// </summary>
        public WeakActionEvent<object> Completed 
		{ 
			get; 
			set; 
		}

    }



    public class RelayCommand<TObject> : System.Windows.Input.ICommand
    {
		/// <summary>
		///		the command's execution method .
		/// </summary>
        private readonly Action<TObject> _executeMethod;

		/// <summary>
		///		check if can the command executes method .
		/// </summary>
        private readonly Func<TObject, bool> _canExecuteMethod;


		/// <summary>
		/// 
		/// </summary>
        public RelayCommand( Action<TObject> executeMethod, Func<TObject, bool> canExecuteMethod )
        {
            this._executeMethod = executeMethod;
            this._canExecuteMethod = canExecuteMethod;
        }

        public RelayCommand(Action<TObject> executeMethod)
        {
            this._executeMethod = executeMethod;
            this._canExecuteMethod = x => true;
        }

		public void Execute ( TObject parameter )
        {
            if ( this._executeMethod != null)
            {
                this._executeMethod( parameter );
            }
        }

		/// <summary>
		/// 
		/// </summary>
		public void Execute ( object parameter )
        {
            Execute((TObject)parameter);
        }

		/// <summary>
		///		Checks if this command can executes .
		/// </summary>
		public bool CanExecute ( TObject parameter )
        {
            return this._canExecuteMethod == null || this._canExecuteMethod(parameter);
        }

       /// <summary>
       /// 
       /// </summary>
        public bool CanExecute( object parameter )
        {
            return CanExecute( (TObject)parameter );
        }

      /// <summary>
      /// 
      /// </summary>
        public event EventHandler CanExecuteChanged
        {
            add
            {
                if (_canExecuteMethod != null)
                {
                    CommandManager.RequerySuggested += value;
                }
            }

            remove
            {
                if (_canExecuteMethod != null)
                {
                    CommandManager.RequerySuggested -= value;
                }
            }
        }

    }

}
